Skip to content

feat(desktop): code-block hover toolbar with copy-as-MD and language picker#3120

Open
HUQIANTAO wants to merge 1 commit into
esengine:main-v2from
HUQIANTAO:feat/code-block-toolbar
Open

feat(desktop): code-block hover toolbar with copy-as-MD and language picker#3120
HUQIANTAO wants to merge 1 commit into
esengine:main-v2from
HUQIANTAO:feat/code-block-toolbar

Conversation

@HUQIANTAO

Copy link
Copy Markdown
Contributor

Code blocks in chat previously had a single hover-revealed Copy button. Replace it with a richer toolbar:

  1. Copy as Markdown: wraps the value in a fenced code block (```lang) so the snippet pastes into a GitHub issue or README with full syntax highlighting preserved.
  2. Language picker: a small chevron button next to the copy buttons. Opens a 30-entry menu of the most common languages the agent emits. The user's manual pick is persisted per-workspace (last 5 picks) in localStorage and used as the smart default for the next unlabelled block in that workspace.
  3. Reserved slots: the toolbar is shaped to accept 'Run in workspace' and 'Open in editor' actions as future bridge additions.

…picker

Code blocks in chat previously had a single hover-revealed Copy button.
Replace it with a richer toolbar:

1. Copy as Markdown: wraps the value in a fenced code block (```lang) so
   the snippet pastes into a GitHub issue or README with full syntax
   highlighting preserved. The leading fence uses the current effective
   language (override, then prop, then the workspace's remembered-most-
   recent pick). Brief check-mark feedback reuses the existing pattern.

2. Language picker: a small chevron button next to the copy buttons.
   Opens a 30-entry menu of the most common languages the agent emits.
   The user's manual pick is persisted per-workspace (last 5 picks) in
   localStorage and used as the smart default for the next unlabelled
   block in that workspace. The override is held in CodeViewer state so
   highlighter re-runs the right hljs grammar; an Escape or outside click
   closes the picker without committing.

3. Reserved slots: the toolbar is shaped to accept 'Run in workspace' and
   'Open in editor' actions as future bridge additions — the layout
   doesn't need to change to add them.

The toolbar wrapper is a flex row at top-right of the code block; the
existing copy button keeps its position. The whole cluster is opacity-0
by default and reveals on :hover/:focus-within with an 80ms delay on the
fade-out so a mouse pass over the picker list doesn't blink the buttons
away mid-hover. prefers-reduced-motion is honored through the existing
@media rule.

New files: lib/codeBlockActions.ts (LANGS + rememberLang + suggestedLang
+ languageLabel), components/CodeBlockToolbar.tsx.
@github-actions github-actions Bot added the v2 Go rewrite (1.x) — main-v2 branch, active development label Jun 4, 2026

@esengine esengine left a comment

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Two state bugs to fix before this lands:

  1. The language override lives in two places (CodeViewer state and CodeBlockToolbar state) and neither resets when props.value changes — a recycled instance in the virtualized transcript carries a stale language onto a different code block (the comment claims it resets; nothing does). Make it one piece of state, keyed/reset on value.
  2. CodeViewer never passes the workspace prop, so the rememberLang/suggestedLang persistence in codeBlockActions.ts is dead code in the only real mount — wire it or delete it.

Also drop the "(Reserved) Run / Open in editor" speculative comment slots per the repo comment policy, and rebase.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

v2 Go rewrite (1.x) — main-v2 branch, active development

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants